package com.datasecops.scannerservices.operation;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.datasecops.scannerservices.config.ConfigFilePath;
import com.datasecops.scannerservices.entity.CommonParam;
import com.datasecops.scannerservices.enumerate.EngineStatus;
import com.datasecops.scannerservices.service.ScannerEngineServer;
import com.datasecops.scannerservices.util.ByteStreamHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**oss对象数据库的操作
 * @author: GeXiaoLong
 * @time: 2022/11/9 14:55
 */
@Service
@Slf4j
public class OssOperation {

    @Resource
    private ScannerEngineServer engineServer;

    //每一批次定1000行
    private int batchLine = 1000;

   /* @Resource
    private ScanDataProcessServer dataProcessServer;*/

//    private static String ENDPOINT = "oss-cn-beijing.aliyuncs.com";//外网访问节点
//    private static String ACCESSKEYID = "LTAI5tS1FnMowceqWBGjephM";//访问秘钥
//    private static String ACCESSKEYSECRET = "ZfIlHuBb1nu7bhH33PQMzUEWJMQYfY";//加密签名字符串和OSS用来验证签名字符串的密钥
//    private static String BUKETNAME = "soulmy"; //存储空间名称
//    //private static String OBJECTNAME = "soul/HotDB数据库.doc";//文件的完整路径
//    // private static String PATHNAME = "P:/soul/HotDB数据库.doc";//文件下载到本地的位置
//    private static String KEYPREFIX = "soul";//指定前缀,扫描此空间下所有的文件
     /**
      *
      * @Description OSS下载文件
      * @author GeXiaoLong
      * @time 2022/11/9 15:00
      * @param
      * @return
      */
    public void download(String objectName,String pathName,String endPoInt,String buketName,String accessKeyId,String accessKeySecret ){
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoInt, accessKeyId, accessKeySecret);

        try {
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
            ossClient.getObject(new GetObjectRequest(buketName, objectName), new File(pathName));
        } catch (OSSException oe) {
            log.error("Failed Method download OSSException:" + oe.getErrorMessage());
        } catch (ClientException ce) {
            log.error("Failed Method download ClientException:" + ce.getErrorMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

     /**
      *
      * @Description OSS扫描文件
      * @author GeXiaoLong
      * @time 2022/11/9 15:00
      * @param
      * @param param
      * @param commonParam
      * @param jobId
      * @param jobName
      * @param scannerID
      * @return
      */
    public void enumerate(String endPoInt, String buketName, String keyPreFix, String accessKeyId, String accessKeySecret, CommonParam param, CommonParam commonParam, String jobId, String jobName, String scannerID) {
        //基础path
        StringBuilder basicPath = new StringBuilder(ConfigFilePath.getScannerDirPath() + File.separator + param.getJobId() + File.separator + param.getUUId());
        //暂存目录
        StringBuilder filePath = new StringBuilder(basicPath);
        String pathway = null;
        int time = 0;

        List<Object> list = new ArrayList<>();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoInt, accessKeyId, accessKeySecret);
        int colIndex = 0;
        try {
            // 列举文件。如果不设置keyPrefix，则列举存储空间下的所有文件。如果设置keyPrefix，则列举包含指定前缀的文件。
            ObjectListing objectListing = ossClient.listObjects(buketName, keyPreFix);
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            pathway = filePath.toString();
            pathway = pathway.replace("\\", "/");
            if (sums.size() > 0){
                mkdir(pathway);
            }
            for (OSSObjectSummary s : sums) {
                char ch = '.';
                if (!s.getKey().contains(ch + "")) {
                    String KEYPREFIX = pathway + "/" + s.getKey();
                    mkdir(KEYPREFIX);
                    continue;
                }
                String objectName = s.getKey();
                list.add(objectName);
                String pathName = pathway + "/" + s.getKey();
                download(objectName, pathName, endPoInt, buketName, accessKeyId, accessKeySecret);
                colIndex++;
            }
        } catch (OSSException oe) {
            log.error("Failed Method enumerate OSSException:" + oe.getErrorMessage());
        } catch (ClientException ce) {
            log.error("Failed Method download ClientException:" + ce.getErrorMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                    xmlFile(param,colIndex,time,pathway,list,basicPath,commonParam,jobId,jobName,scannerID);
                    time++;
            }
        }
    }

    public void xmlFile(CommonParam param, int colIndex, int time, String pathway, List list, StringBuilder basicPath, CommonParam commonParam, String jobId, String jobName, String scannerID){
        while (true){
            //>>>>>>>>>>>说明XML文件落盘
            Element rootElem = DocumentHelper.createElement("TaskInfo");
            rootElem.addAttribute("Type","FileServer");
            //ServerInfo
     /*       Element dbInfoElem = DocumentHelper.createElement("DBInfo");
            dbInfoElem.addAttribute("dbtype","AliOss");//数据类型
            dbInfoElem.addAttribute("serverip",param.getIp());//数据库地址
            dbInfoElem.addAttribute("serverPort",param.getPort()+"");//端口
            dbInfoElem.addAttribute("dbname",param.getDbName());//数据库名称
            dbInfoElem.addAttribute("tablename",param.getTableName());//表名称
            dbInfoElem.addAttribute("tablerowcount","1");//表总行数(文件数)
            dbInfoElem.addAttribute("tableindex",time+"");//第几批次
            dbInfoElem.addAttribute("resguid",param.getUUId());//uuId
            dbInfoElem.addAttribute("db_relation_type","OSS");//关系型数据库
            rootElem.add(dbInfoElem);*/

            String rootName = param.getIp();
            if (StringUtils.isNotBlank(param.getDbName())){
                rootName = rootName + "/" + param.getDbName();
            }
            Element sererInfoElem = DocumentHelper.createElement("ServerInfo");
            sererInfoElem.addAttribute("servertype","OSS");//数据类型
            sererInfoElem.addAttribute("serverip",param.getIp());//数据库地址
            sererInfoElem.addAttribute("serverPort",param.getPort()+"");//端口
            sererInfoElem.addAttribute("credentialname","");//凭证名称
            sererInfoElem.addAttribute("username","");
            sererInfoElem.addAttribute("rootname",rootName);
            sererInfoElem.addAttribute("devicename","");
            sererInfoElem.addAttribute("resguid",param.getUUId());
            rootElem.add(sererInfoElem);


            //TaskkBaseInfo
            Element taskkBaseInfo = DocumentHelper.createElement("TaskBaseInfo");
            taskkBaseInfo.addAttribute("TaskID",jobId);
            taskkBaseInfo.addAttribute("TaskName",jobName);
            taskkBaseInfo.addAttribute("ScannerID",scannerID);
            rootElem.add(taskkBaseInfo);

            //TaskkProgressInfo
            Element taskkProgressInfo = DocumentHelper.createElement("TaskProgressInfo");
            taskkProgressInfo.addAttribute("sum_file_count","0");
            taskkProgressInfo.addAttribute("cur_file_pos","0");
            taskkProgressInfo.addAttribute("cur_file_count","0");
            rootElem.add(taskkProgressInfo);

            //DB_Policy
            Element dbPolicy = DocumentHelper.createElement("DBPolicy");
            dbPolicy.addAttribute("PolicyPath",commonParam.getPolicyPath());
            dbPolicy.addAttribute("FingerPath",commonParam.getFingerPath());
            dbPolicy.addAttribute("DictPath",commonParam.getDictPath());
            dbPolicy.addAttribute("MchClusterPath",commonParam.getMchClusterPath());
            rootElem.add(dbPolicy);

            //DB_DATA
     /*       Element dbDataElem = DocumentHelper.createElement("DBData");
            Element colData;
            String path;
            int times = 0;
            for (int i = 1; i <= colIndex;) {
                colData = DocumentHelper.createElement("ColData");
                colData.addAttribute("name","");
                path = pathway + "/" + list.get(0);
                list.remove(0);
                colIndex--;
                times++;
                colData.addAttribute("Path",path);
                dbDataElem.add(colData);
                if (times==1000){
                    break;
                }
            }
            time++;
            rootElem.add(dbDataElem);
*/
            //FileList
            Element fileListElem = DocumentHelper.createElement("FileList");
            Element colData;
            String path;
            String serverPath;
            int times = 0;
            for (int i = 1; i <= colIndex;) {
                colData = DocumentHelper.createElement("FileItem");

                path = pathway + "/" + list.get(0);
                serverPath = param.getIp() + "/" + param.getDbName() +  "/" +  list.get(0);
                colData.addAttribute("ServerPath",serverPath);
                colData.addAttribute("LocalPath",path);

                list.remove(0);
                colIndex--;
                times++;
                fileListElem.add(colData);
                if (times==1000){
                    break;
                }
            }
            time++;
            rootElem.add(fileListElem);

            OutputStreamWriter xmlWriter = null;
            StringBuilder xmlPath = new StringBuilder(basicPath);

           /* xmlPath.append(File.separator).append("config_").append(param.getDbName()).append("_").append(param.getModel()).append("_").append(time).append(".xml");*/
            xmlPath.append(File.separator).append("config_").append(param.getDbName()).append(".xml");//去除指定的存储空间
            try {
                String xmlStr = ByteStreamHelper.toXmlString(rootElem);
                byte[] bom = {-1, -2};
                FileOutputStream outputStream = new FileOutputStream(xmlPath.toString());
                outputStream.write(bom);

                xmlWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_16LE);
                BufferedWriter bw = new BufferedWriter(xmlWriter);
                bw.write(xmlStr);
                bw.flush();
                bw.close();
            } catch (Exception e) {
                log.error("Failed Method Write xml error: " + e.getMessage());
            }finally {
                if (null != xmlWriter){
                    try {
                        xmlWriter.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("Failed Method Write xml error2: " + e.getMessage());
                    }
                }
                //调用引擎传输数据
                engineServer.callScannerEngine(param.getJobId(), "scanproxy", EngineStatus.DATA.getValue(),xmlPath.toString());
                log.error("oss的检索引擎收到信息了吧?");
                if (colIndex == 0){
                    return;
                }
            }
        }

    }


     /**
      *
      * @Description  OSS创建文件夹
      * @author GeXiaoLong
      * @time 2022/11/9 15:00
      * @param
      * @return
      */
    public void mkdir(String KEYPREFIX){
        new File(KEYPREFIX).mkdirs();
    }

    public static void main(String[] args) {
        //enumerate();
        //download();
    }
}
